using System;
using UnityEngine;
using Decision_Tree;

public class AgentDecisionTree
{
	/*private GetEnergyBehaviour getEnergyBehaviour;
	private FindExitBehaviour findExitBehaviour; 
	private FleeBehaviour fleeBehaviour;*/ 	
		
	private DecisionTree decisionTree;
	private GameController gameController; 
	// Reference to the agent we get information to use in the decision tree from
	private AgentBehaviourScript agent;
	// Reference to the maze
	private Maze maze;
	
	private Decision_Tree.Actions currentAction;
	private Plan currentPlan = null;
	
	public AgentDecisionTree (AgentBehaviourScript agent)
	{
		currentAction = Decision_Tree.Actions.DEFAULT;
		this.agent = agent;
		gameController = (GameController)GameObject. FindWithTag("GameController").GetComponent("GameController");
		this.maze = gameController.getMaze(); 
		decisionTree = new Decision_Tree.DecisionTree(gameController.getKnowledgeEnabled());
		
		/*
		getEnergyBehaviour = new GetEnergyBehaviour();
		findExitBehaviour = new FindExitBehaviour();
		fleeBehaviour = new FleeBehaviour();
		*/	
	}
	
	public void rebuildTree()
	{
		decisionTree = new Decision_Tree.DecisionTree(gameController.getKnowledgeEnabled());
	}
	
	private void print(string s)
	{
		MonoBehaviour.print(s);	
	}	
	
	public Plan getCurrentPlan()
	{		                                
		Decision_Tree.Actions action = decisionTree.makeDecision(agent.brain);
		currentAction = action;
		
		if (action == Actions.MoveTowardsFood && agent.getNearestEnergy() == null)
		{
			action = Actions.MoveTowardsGoal;
		}		
		
		switch ((int)action)
		{
			case (int)Decision_Tree.Actions.Lost:
				if (currentPlan	== null || !(currentPlan is PlanLost))
					currentPlan = new PlanLost(agent,maze);
				break;		
			case (int)Decision_Tree.Actions.MoveTowardsGoal:
				//agent.setDestination(findExitBehaviour.getSteering(agent));
				if (currentPlan	== null || !(currentPlan is PlanGoToGoal))
			    	currentPlan = new PlanGoToGoal(agent, maze);	
				break;
			case (int)Decision_Tree.Actions.MoveTowardsFood:
				// If we arn't already on a plan to find food create a new one
				if (currentPlan	== null || !(currentPlan is PlanGetNearestEnergy))
			    	currentPlan = new PlanGetNearestEnergy(agent, maze);	
				break;
			case (int)Decision_Tree.Actions.EvadeHerder:
				//Maybe check if current plans path will not go near the herder?
				if (currentPlan != null && currentPlan is PlanEvadeHerder)
				{
					//Already evading - maybe should reevade if a certain amount of time has past
					break;
				}
				
				if(currentPlan != null && currentPlan.getPathPlanner() != null)
				{
					Vector3 currentGoal = currentPlan.getPathPlanner().get_goal();
					currentPlan = new PlanEvadeHerder(agent,maze,currentGoal);
				}
				else
				{
					// We didn't have a plan but need to evade the herder
					currentPlan = new PlanEvadeHerder(agent, maze, agent.getNearestExit());
				}
				break;
			default:	
				agent.setDestination(agent.getPosition());
				break;
		}
		
		//set agent colour as based on state
		switch ((int)action)
		{
			case (int)Decision_Tree.Actions.Lost:
				agent.ChangeColour(Color.white);
				break;		
			case (int)Decision_Tree.Actions.MoveTowardsGoal:
				agent.ChangeColour(Color.green);
				break;
			case (int)Decision_Tree.Actions.MoveTowardsFood:
				agent.ChangeColour(Color.blue);	
				break;
			case (int)Decision_Tree.Actions.EvadeHerder:
				agent.ChangeColour(Color.red);	
				break;
			default:	
				agent.ChangeColour(Color.white);	
				break;
		}

		
	//	Removed: the agent will store and execute the plan returne
	/*
    if (currentPlan != null)
		{
			pathplanner path = currentPlan.getPathPlanner();
			if (path != null)
				path.debug_drawing();
			
			if (!currentPlan.execute())	
				currentPlan = null;
		}
	*/
		return currentPlan;
		
		
	}
	
	public pathplanner getPlanner()
	{
		if (currentPlan	!= null)
		{
			return currentPlan.getPathPlanner();	
		}
		return null;
	}
	
	public string getActionAsString()
	{
		switch ((int)currentAction)
		{
			//TODO replace set destination calls with path finding
			case (int)Decision_Tree.Actions.MoveTowardsGoal:
				return "Finding Goal";
			case (int)Decision_Tree.Actions.MoveTowardsFood:
				return "Finding Energy";
			case (int)Decision_Tree.Actions.EvadeHerder:
				return "Evading Herder";
			case (int)Decision_Tree.Actions.Lost:
				return "Lost";
			default:	
				return "Default";
		}	
	}
}

